package gases.as3.librarys.core.net.cpp.struct
{
	import flash.utils.ByteArray;
	
	import gases.as3.librarys.core.net.socket.SocketUtil;

	public class StructUtil
	{
		/**
		 * 解码ByteArray, 返回相应的Struct
		 * @param bytes
		 * @param struct
		 * @return 
		 * 
		 */		
		public static function decode(bytes:ByteArray,struct:Struct):Struct
		{
			var len:int = struct.length;
			for(var i:int = 0; i < len; i++)
			{
				if(bytes.position == bytes.length)
					return struct;
				
				var element:StructElement = struct.getElement(i) as StructElement;
				if(!element)
					continue;
				var name:String = element.name;
				switch(element.type)
				{
					case StructType.DATA_TYPE_INT:
						element.value = SocketUtil.readInt(bytes);
						break;
					
					case StructType.DATA_TYPE_INT64:
//						element.value = SocketUtil.readInt64(bytes);
						element.value = bytes.readDouble();
						break;
					
					case StructType.DATA_TYPE_CHAR:
						var cp:int = bytes.position;
						element.value = bytes.readMultiByte(element.length, 'gb2312');
						bytes.position = cp + element.length;
						break;
					
					case StructType.DATA_TYPE_BOOL:
						element.value = bytes.readBoolean();
						break;
					
					case StructType.DATA_TYPE_BYTE:
						element.value = bytes.readByte();
						break;
					
					case StructType.DATA_TYPE_BYTES:
						var ba:ByteArray = new ByteArray();
						bytes.readBytes(ba, 0, element.length);
						if(element.value is Struct)
						{
							element.value = StructUtil.decode(ba,element.value);
						}
						else
						{
							element.value = ba;
						}
						break;
					
					case StructType.DATA_TYPE_SHORT:
						element.value = SocketUtil.readShort(bytes);
						break;
				}
			}
			return struct;
		}
		
		/**
		 * 编码Stuct,存储在ByteArray里面返回
		 * @param struct
		 * @return
		 * 
		 */		
		public static function encode(struct:Struct):ByteArray
		{
			var bytes:ByteArray = new ByteArray();
			var len:int = struct.length;
			for(var i:int = 0; i < len;i++)
			{
				var element:StructElement = struct.getElement(i) as StructElement;
				if(!element)
					continue;
				switch(element.type)
				{
					case StructType.DATA_TYPE_INT:
						SocketUtil.writeInt(element.value,bytes);
						break;
					
					case StructType.DATA_TYPE_INT64:
//						SocketUtil.writeInt64(element.value,bytes);
						bytes.writeDouble(element.value);
						break;
					
					case StructType.DATA_TYPE_CHAR:
						var cp : int = bytes.position;
						if(element.value)
							bytes.writeMultiByte(element.value, 'gb2312');
						if(bytes.position < cp + element.length)
						{
							bytes.position = cp + element.length - 1;
							bytes.writeByte(0);
						}
						break;
					
					case StructType.DATA_TYPE_BOOL:
						bytes.writeBoolean(element.value);
						break;
					
					case StructType.DATA_TYPE_BYTE:
						bytes.writeByte(element.value);
						break;
					
					case StructType.DATA_TYPE_BYTES:
						if(element.value is ByteArray)
						{
							bytes.writeBytes(element.value);
						}
						else if(element.value is Struct)
						{
							bytes.writeBytes(StructUtil.encode(Struct(element.value)));
						}
						else
						{
							throw new Error('DATA_TYPE_BYTES writes error!');
						}
						break;
					
					case StructType.DATA_TYPE_SHORT:
						SocketUtil.writeShort(element.value, bytes);
						break;
				}
			}
			
			return bytes;
			
		}
	}
}